package com.nirvana.utils;

import com.nirvana.config.PluginConfig;
import com.nirvana.data.DaoGenerateContext;
import com.nirvana.data.DbFieldInfo;
import com.nirvana.generate.OrmEntityGenerator;
import com.nirvana.type.DaoOption;

import java.util.List;
import java.util.Map;

/**
 * @author: create by skinjay
 * @date:2021/6/23
 */
public class BusinessCodeUtil {
    public static String generateBusinessCode() {
        return """
                package %s;
                
                %s
                
                public class %s {
                %s
                }
                """.formatted(
                PluginConfig.getInstance().getBusinessPackage(),
                generateImport(),
                CommonUtil.CreateBusinessName(OrmEntityGenerator.context.entityName),
                generateMethod()
        );
    }

    private static String generateImport() {
        DaoGenerateContext context = OrmEntityGenerator.context;
        Map<String, Boolean> options = context.options;
        StringBuilder content = new StringBuilder();
        if (options.get(DaoOption.GET_ENTITY_BY_ALL_PRIMARY_KEY)
                || options.get(DaoOption.GET_ENTITY_LIST_BY_FIST_PRIMARY_KEY)
                || options.get(DaoOption.UPDATE_ENTITY)
                || options.get(DaoOption.UPDATE_ENTITY_BATCH)) {
            content.append("""
                    import %s.%s;
                    import %s.%s;
                    """.formatted(
                    CommonUtil.generateDaoEntityPackage(),
                    context.entityName,
                    PluginConfig.getInstance().getFactoryPackage(),
                    CommonUtil.CreateFactoryName(context.entityName)
            ));
        }
        if (options.get(DaoOption.GET_ENTITY_LIST_BY_FIST_PRIMARY_KEY) || options.get(DaoOption.UPDATE_ENTITY_BATCH)) {
            content.append("import java.util.List;\n");
        }
        return content.toString();
    }

    private static String generateMethod() {
        StringBuilder content = new StringBuilder();
        Map<String, Boolean> options = OrmEntityGenerator.context.options;
        if (options.get(DaoOption.GET_ENTITY_BY_ALL_PRIMARY_KEY)) {
            content.append(generateGetEntityByAllPrimaryKey());
        }
        if (options.get(DaoOption.GET_ENTITY_LIST_BY_FIST_PRIMARY_KEY)) {
            content.append(generateGetEntityByFirstPrimaryKey());
        }
        if (options.get(DaoOption.UPDATE_ENTITY)) {
            content.append(generateUpdateEntity());
        }
        if (options.get(DaoOption.UPDATE_ENTITY_BATCH)) {
            content.append(generateUpdateEntityBatch());
        }
        return content.toString();
    }

    private static String generateGetEntityByAllPrimaryKey() {
        DaoGenerateContext context = OrmEntityGenerator.context;
        List<DbFieldInfo> primaryFields = context.primaryFields;
        String entityName = context.entityName;
        return """
                    public static %s {
                        return %s.getDao().getByKey(%s);
                    }
                
                """.formatted(
                getEntityByKeysMethodSign(entityName, primaryFields),
                CommonUtil.CreateFactoryName(entityName),
                CommonUtil.createPrimaryMethodInvokeParams(primaryFields)
        );
    }

    public static String getEntityByKeysMethodSign(String entityName, List<DbFieldInfo> primaryFields) {
        return """
                %s get%sByKeys(%s)
                """.formatted(
                entityName,
                entityName,
                CommonUtil.createPrimaryMethodParams(primaryFields)
        ).trim();
    }

    private static String generateGetEntityByFirstPrimaryKey() {
        DaoGenerateContext context = OrmEntityGenerator.context;
        String entityName = context.entityName;
        List<DbFieldInfo> primaryFields = context.primaryFields.stream().findFirst().stream().toList();
        return """
                    public static %s {
                        return %s.getDao().get%sListBy%s(%s);
                    }
                
                """.formatted(
                getEntityByFirstKeyMethodSign(entityName, primaryFields),
                CommonUtil.CreateFactoryName(entityName),
                entityName,
                CommonUtil.createPrimaryMethodName(primaryFields),
                CommonUtil.createPrimaryMethodInvokeParams(primaryFields)
        );
    }

    public static String getEntityByFirstKeyMethodSign(String entityName, List<DbFieldInfo> primaryFields) {
        return """
                List<%s> get%sBy%s(%s)
                """.formatted(
                entityName,
                entityName,
                CommonUtil.createPrimaryMethodName(primaryFields),
                CommonUtil.createPrimaryMethodParams(primaryFields)
        ).trim();
    }

    private static String generateUpdateEntity() {
        DaoGenerateContext context = OrmEntityGenerator.context;
        String entityName = context.entityName;
        String lowEntityName = context.lowEntityName;
        return """
                    public static %s {
                        %s.getDao().addOrUpdate(%s);
                    }
                
                """.formatted(
                updateEntityMethodSign(entityName, lowEntityName),
                CommonUtil.CreateFactoryName(entityName),
                lowEntityName
        );
    }

    public static String updateEntityMethodSign(String entityName, String lowEntityName) {
        return """
                void update%s(%s %s)
                """.formatted(entityName, entityName, lowEntityName).trim();
    }

    private static String generateUpdateEntityBatch() {
        DaoGenerateContext context = OrmEntityGenerator.context;
        String entityName = context.entityName;
        String lowEntityName = context.lowEntityName;
        return """
                    public static %s {
                        %s.getDao().addOrUpdateBatch(%s);
                    }
                """.formatted(
                updateEntityBatchMethodSign(entityName, lowEntityName),
                CommonUtil.CreateFactoryName(entityName),
                lowEntityName
        );
    }

    public static String updateEntityBatchMethodSign(String entityName, String lowEntityName) {
        return """
                void update%sBatch(List<%s> %s)
                """.formatted(entityName, entityName, lowEntityName).trim();
    }
}
